<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<link rel="stylesheet" type="text/css" href="../css/common.css" media="all" />
<link rel="stylesheet" type="text/css" href="../css/article.css" media="all" />
</head>
<body>
<div id="w3h_body">
  <div class="body_content">
    <!-- toc begin -->
    <h1 class="title">SD2023: IE Chrome Safari 在计算 'overflow' 特性值为 visible 的容器的 scrollHeight 的值时会考虑其内脱离了文本流的元素</h1>
    <ul class="toc">
      <li><a href="#standard_reference">标准参考</a> <span>•</span></li>
      <li><a href="#description">问题描述</a> <span>•</span></li>
      <li><a href="#influence">造成的影响</a> <span>•</span></li>
      <li><a href="#impacted_browsers">受影响的浏览器</a> <span>•</span></li>
      <li><a href="#analysis_of_issues">问题分析</a> <span>•</span></li>
      <li><a href="#solutions">解决方案</a> <span>•</span></li>
      <li><a href="#see_also">参见</a></li>
    </ul>
    <!-- toc end -->
    <div id="w3h_content">
      <!-- content begin -->
      <address class="author">作者：钱宝坤</address>
    <h2 id="standard_reference">标准参考</h2>
    <p>无。</p>

    <h2 id="description">问题描述</h2>
    <p>各浏览器计算不包含在普通流中的内容元素的 scrollHeight 值时结果有差异。</p>

    <h2 id="influence">造成的影响</h2>
    <p>造成不同浏览器下 scrollHeight 属性返回值各有不同，从而可能使依赖这个数值的应用功能点出现问题。</p>

    <h2 id="impacted_browsers">受影响的浏览器</h2>
    <table class="list">
      <tr>
        <th>IE Chrome Safari</th>
        <td>&nbsp;</td>
      </tr>
    </table>

    <h2 id="analysis_of_issues">问题分析</h2>
    <p>scrollHeight 最初是由 IE4.0 以上版本提供的私有属性，至今为止所有主流浏览器均支持这个属性。更多详细内容请参见 MSDN 描述：<a href="http://msdn.microsoft.com/en-us/library/ms534615(VS.85).aspx">scrollHeight Property</a>。</p>
    <p>在 W3C HTML5 草案中，已将 scroll 系列属性规范化，包括 scrollHeight，详细内容可参见：<a href="http://www.w3.org/TR/cssom-view/#scroll-attributes">7.2 The scrollTop, scrollLeft, scrollWidth, and scrollHeight attributes</a>。</p>
    <p>正是由于他是个非标准属性，各个浏览器对如何计算 scrollHeight 属性的值存在歧义。</p>
    <p>在 IE 中，若一个容器 'overflow' 特性值为 'visible'，容器内的元素脱离了文本流，但该容器仍然是其包含块，则在计算容器的 scrollHeight 的值时会考虑脱离了文本流的元素。</p>
    <p>分析如下代码：</p>
<pre>
&lt;div id="A" style="background:red;"&gt;
  &lt;span style="width:100px;height:100px;float:left;"&gt;content&lt;/span&gt;
&lt;/div&gt;

&lt;script language="javascript"&gt;
  alert(document.getElementById("A").scrollHeight);
&lt;/script&gt;
</pre>
    <p>代码中 A 容器仅包含一个浮动流中的子元素，容器高度没有设置采用 auto 值，子元素处于浮动流后，A 容器在正常流中没有内容，其实际高度为 0。</p>
    <p>那么 scrollHight 应该如何计算呢？ 请看下列浏览器实际计算值：</p>
      <table class="compare">
              <tr>
                <th>&nbsp;</th>
                <th>IE</th>
                <th>Chrome Safari Firefox Opera</th>
              </tr>
              <tr>
                <th>scrollHeight</th>
                <td>100</td>
                <td>0</td>
              </tr>
            </table>
      <p>明显看出此种情况下 IE 中在计算容器的 scrollHeight 值时会考虑脱离了普通流的元素。</p>
      <p>&nbsp;</p>
      <p>再看另一种情况，如果容器也脱离普通流，进入定位流后又该如何？</p>
      <p>在 <em>Chrome Safari</em> 中，在 IE 中条件的基础上，若容器的 'position' 特性不为 'static'，并且没有创建新的 <a href="http://www.w3.org/TR/CSS21/visuren.html#block-formatting">Block formatting context</a> ，则在计算容器的 scrollHeight 的值时会考虑脱离了普通流的元素。</p>
      <p>根据 CSS 2.1 规范说明，当元素拥有绝对定位样式后，会创建新的 <a href="http://www.w3.org/TR/CSS21/visuren.html#block-formatting">Block formatting context</a>，此时处于浮动流中的子元素可以被容器计算高度。所有浏览器均遵循这个规范，实际计算 scrollHeight 值相同。但是父容器拥有相对定位样式时，是不会创建新的 <a href="http://www.w3.org/TR/CSS21/visuren.html#block-formatting">Block formatting context</a> 的。</p>
      <p>分析如下代码：</p>
<pre>
&lt;div id="A" style="position:relative; background:red;"&gt;
  &lt;span style="width:100px;height:100px;float:left;"&gt;content&lt;/span&gt;
&lt;/div&gt;

&lt;script language="javascript"&gt;
  alert(document.getElementById("A").scrollHeight);
&lt;/script&gt;
</pre>

      <p>代码中 A 容器处于定位流中，且仅包含一个浮动流中的子元素，容器高度没有设置采用 auto 值，子元素处于浮动流后，A 容器在正常流中没有内容，其实际高度为 0。</p>
      <p>那么此时的 scrollHight 应该如何计算呢？ 请看下列浏览器实际计算值：</p>
      <table class="compare">
        <tr>
          <th>&nbsp;</th>
          <th>IE Chrome Safari </th>
          <th>Firefox Opera</th>
        </tr>
        <tr>
          <th>scrollHeight</th>
          <td>100</td>
          <td>0</td>
        </tr>
      </table>
      <p>明显看出当父容器在定位流中的情况下 <em>IE Chrome Safari</em> 中在计算容器的 scrollHeight 值时，均会考虑脱离了普通流的元素。</p>

      <h2 id="solutions">解决方案</h2>
      <p>确保读取 scrollHeight 属性的元素均创建了新的 block formatting context，或者此容器与内部子容器处于同一文档流中，以此避免各浏览器中读数不同。</p>

      <h2 id="see_also">参见</h2>
      <h3>知识库</h3>
      <ul class="see_also">
        <li><a href="#">...</a></li>
      </ul>

      <h3>相关问题</h3>
      <ul class="see_also">
        <li><a href="#">...</a></li>
      </ul>

      <div class="appendix">
        <h2>测试环境</h2>
        <table class="list">
          <tr>
            <th>操作系统版本:</th>
            <td>Windows 7 Ultimate build 7600</td>
          </tr>
          <tr>
            <th>浏览器版本:</th>
            <td>
              IE6<br />
              IE7<br />
              IE8<br />
              Firefox 3.6.8<br />
              Chrome 6.0.472.11 dev<br />
              Safari 5.0.1<br />
              Opera 10.60
            </td>
          </tr>
          <tr>
            <th>测试页面:</th>
            <td><a href="../../tests/SD2023/float_scrollHeight.html">float_scrollHeight.html</a> <br />
                          <a href="../../tests/SD2023/position_scrollHeight.html">position_scrollHeight.html</a>
                        </td>
          </tr>
          <tr>
            <th>本文更新时间:</th>
            <td>2010-08-02</td>
          </tr>
        </table>

        <h2>关键字</h2>  
        <!-- keywords begin -->
        <p>height 0 scrollHeight 高度</p>
        <!-- keywords end -->
      </div>
      <!-- content end -->
    </div>
  </div>
</div>
</body>
</html>
